package com.mrzhou.auth.serialize;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.mrzhou.auth.constant.AuthConstant;
import com.mrzhou.auth.support.IntegrationAuthenticationContext;
import com.mrzhou.auth.support.IntegrationAuthenticationEntity;
import com.mrzhou.auth.support.SimpleUser;
import com.mrzhou.auth.support.aspect.ResultResponse;
import com.mrzhou.auth.utils.TokenUtil;
import com.mrzhou.core.tool.constants.TokenConstant;
import com.mrzhou.core.tool.utils.DataUtil;
import com.mrzhou.core.tool.utils.Func;
import com.mrzhou.data.support.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 *  登录成功后的json处理,
 *  	用于自定义返回json格式
 */
@Component
public class LoginSuccessJsonSerializer extends StdSerializer<ResultResponse> {

	@Autowired
	private RedisService redisService;

	/*  序列化器的构造方法使用此方法 */
	protected LoginSuccessJsonSerializer() {
		super(ResultResponse.class);
	}

	@Override
	public void serialize(ResultResponse value, JsonGenerator gen, SerializerProvider provider) throws IOException {
		OAuth2AccessToken oAuth2AccessToken = (OAuth2AccessToken) value.getData();

		gen.writeStartObject();
		gen.writeNumberField("code", HttpStatus.OK.value());
		gen.writeStringField("msg", "登录成功！");
		gen.writeObjectFieldStart("data");
		handlerArgs(gen, oAuth2AccessToken);
		gen.writeEndObject();

		gen.writeEndObject();
	}

	private void handlerArgs(JsonGenerator gen, OAuth2AccessToken oAuth2AccessToken) throws IOException {
		// 获取当前线程的上下文中获取参数
		IntegrationAuthenticationEntity entity = IntegrationAuthenticationContext.get();
		if(Func.toBoolean(entity.getAuthParameter(TokenUtil.FLAG_CODE_PARAM))) { // 是否需要返回授权码
			writeAuthCode(gen, oAuth2AccessToken);
		} else {
			writeNormalInfo(gen, oAuth2AccessToken);
		}
	}

	/**
	 * 处理返回的授权逻辑,
	 * @param gen
	 * @param oAuth2AccessToken
	 * @throws IOException
	 */
	private void writeAuthCode(JsonGenerator gen, OAuth2AccessToken oAuth2AccessToken) throws IOException {
		Map<String, Object> resultParam = oAuth2AccessToken.getAdditionalInformation();
		String code = DataUtil.randomStr(AuthConstant.AUTH_CODE_LENGTH);
		String key = AuthConstant.REDIS_PREFIX_AUTH_CODE + resultParam.get(TokenUtil.CLIENT_ID) + ":" + code;
		SimpleUser user = new SimpleUser();
		user.setStatus(AuthConstant.AUTH_CODE_STATUS_NOT_USE);
		user.setUserId(Func.toLong(resultParam.get(TokenUtil.USER_ID)));
		redisService.set(key, user, AuthConstant.Auth_CODE_TIME_OUT); // 保存到redis缓存
		gen.writeStringField(TokenUtil.AUTH_CODE, code);
		gen.writeNumberField(TokenConstant.EXPIRES_IN, AuthConstant.Auth_CODE_TIME_OUT);
	}

	/**
	 * 处理正常认证后返回的json格式
	 */
	private void writeNormalInfo(JsonGenerator gen, OAuth2AccessToken oAuth2AccessToken) throws IOException {
		Map<String, Object> resultParam = oAuth2AccessToken.getAdditionalInformation();
		gen.writeStringField(TokenConstant.ACCESS_TOKEN, oAuth2AccessToken.getValue());
		gen.writeStringField(TokenConstant.TOKEN_TYPE, oAuth2AccessToken.getTokenType());
		gen.writeStringField(TokenConstant.REFRESH_TOKEN, oAuth2AccessToken.getRefreshToken().getValue());
		gen.writeNumberField(TokenConstant.EXPIRES_IN, oAuth2AccessToken.getExpiresIn());
		String[] scope = new String[1];
		gen.writeStringField("scope", oAuth2AccessToken.getScope().toArray(scope)[0]);
		gen.writeStringField(TokenConstant.ROLE_NAME, Func.toStr(resultParam.get(TokenConstant.ROLE_NAME)));
		gen.writeStringField(TokenConstant.USER_ID, Func.toStr(resultParam.get(TokenConstant.USER_ID)));
		gen.writeStringField(TokenConstant.PHONE, Func.toStr(resultParam.get(TokenConstant.PHONE)));
		gen.writeStringField(TokenConstant.NAME, Func.toStr(resultParam.get(TokenConstant.NAME)));
		gen.writeStringField(TokenConstant.REAL_NAME, Func.toStr(resultParam.get(TokenConstant.REAL_NAME)));
		gen.writeStringField(TokenConstant.AVATAR, Func.toStr(resultParam.get(TokenConstant.AVATAR)));
		gen.writeStringField(TokenConstant.EMAIL, Func.toStr(resultParam.get(TokenConstant.EMAIL)));
		gen.writeStringField(TokenConstant.CLIENT_ID, Func.toStr(resultParam.get(TokenConstant.CLIENT_ID)));
		gen.writeStringField(TokenConstant.ACCOUNT, Func.toStr(resultParam.get(TokenConstant.ACCOUNT)));
		gen.writeStringField("jti",oAuth2AccessToken.getAdditionalInformation().get("jti").toString());
	}


}
